package com.aratana.ui.fields;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPasswordField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

import com.aratana.ui.InputChangeListener;
import com.aratana.ui.ValueChangeListener;
import com.aratana.ui.ViewField;
import com.aratana.util.BinaryUtilities;

@SuppressWarnings("serial")
public class PasswordField extends JPasswordField implements ViewField<byte[]> {

	private boolean obrigatory = false;

	private Color originalBackground;

	protected boolean allSelected = false;

	private int max = -1;
	private int min = -1;
	
	private final List<InputChangeListener> input = new ArrayList<InputChangeListener>();

	public PasswordField() {
		setFont(TAHOMA_13);
		addFocusListener(new FocusAdapter() {

			@Override
			public void focusGained(final FocusEvent e) {
				selectAll();
			}
		});

		setDocument(new PlainDocument() {

			@Override
			public void insertString(final int offs, final String str, final AttributeSet a) throws BadLocationException {
				super.insertString(offs, (getMax() > 0 && str.length() + PasswordField.this.getPassword().length > getMax() ? str.substring(0, getMax() - PasswordField.this.getPassword().length) : str), a);
				fireInputChanged();
			}
		});

		addKeyListener(new KeyAdapter() {

			@Override
			public void keyPressed(final KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_DELETE) {
					setText("");
					e.consume();
				} else if ((e.getModifiers() | InputEvent.CTRL_DOWN_MASK) != InputEvent.CTRL_DOWN_MASK) {
					if (e.getKeyCode() == KeyEvent.VK_A) {
						allSelected = true;
					}
				} else {
					allSelected = false;
				}
			}
		});
	}

	@Override
	public void addValueChangeListener(final ValueChangeListener<byte[]> listener) {
	}
	
	@Override
	public void addInputChangeListener(InputChangeListener listener) {
		input.add(listener);
	}

	public boolean removeInputChangeListener(final InputChangeListener listener) {
		return input.remove(listener);
	}

	public void removeAllInputChangeListener() {
		input.clear();
	}
	
	protected void fireInputChanged() {
		for (InputChangeListener l : input) {
			l.inputChange(this);
		}
	}

	public void setMax(int max) {
		this.max = max;
	}

	@Override
	public int getMax() {
		return max;
	}

	public void setMin(int min) {
		this.min = min;
	}

	@Override
	public int getMin() {
		return min;
	}

	@Override
	public byte[] getValue() {
		try {
			return getStringValue(new String(getPassword()));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	};

	@Override
	public boolean isObrigatory() {
		return obrigatory;
	}

	@Override
	protected void paintComponent(final Graphics g) {
		super.paintComponent(g);
	}

	@Override
	protected void processFocusEvent(final FocusEvent e) {
		if (e.getID() == FocusEvent.FOCUS_GAINED && isEditable()) {
			if (originalBackground == null) {
				originalBackground = getBackground();
			}
			setBackground(SELECTED_BACKGROUND);
		} else if (originalBackground != null) {
			setBackground(originalBackground);
			originalBackground = null;
		}
		super.processFocusEvent(e);
	}

	public void setLimit(final int limit) {
		this.max = limit;
	}

	public void setObrigatory(final boolean obrigatory) {
		this.obrigatory = obrigatory;
	}

	@Override
	public byte[] setValue(byte[] value) {
		return null;
	}

	@Override
	public Class<byte[]> getFieldClass() {
		return byte[].class;
	}

	@Override
	public byte[] getStringValue(String str) throws Exception {
		return str.length() == 0 ? null : BinaryUtilities.byteToHexa(BinaryUtilities.getMd5(str.getBytes()));
	}

	@Override
	public String getValueString(byte[] value) {
		return new String(value);
	}
}
